//
//  MDHCycleScrollView.swift
//  MDHPT
//
//  Created by MengYou on 2019/8/5.
//  Copyright © 2019年 高得华. All rights reserved.
//

import UIKit

//MARK: - ==== 枚举
///滑动的方向
@objc public enum MDHScrollDirection: Int {
    ///横向滑动
    case horizontal = 0
    ///垂直滑动
    case vertical   = 1
}
///分页控件的样式
@objc public enum MDHCycleScrollViewPageControlStyle: Int {
    ///系统的控件
    case classic      = 1
    ///推荐一个很好很强大的自定义的 PageControl 轮子：https://github.com/ChiliLabs/CHIPageControl
    ///默认情况
    case jalapeno     = 2
    ///
    case aleppo       = 3
    ///
    case jaloro       = 4
    ///
    case chimayo      = 5
    ///
    case puya         = 6
    ///
    case paprika      = 7
    ///
    case fresno       = 8
    ///
    case aji          = 9
}
///分页控件的位置
@objc public enum MDHCycleScrollViewPageControlAliment: Int {
    ///默认样式 中间
    case center = 0
    ///居右
    case right = 1
}


///标识
fileprivate let cellIdentifier = "MDHCycleScrollCollectionViewCell"

///DataSource 和 delegate
@objc public protocol MDHCycleScrollViewDelegate : NSObjectProtocol {
    /// 如果你需要自定义cell样式，请在实现此代理方法返回你的自定义cell的class。 */
    @objc optional func customCollectionViewCellClassFor(cycleScrollView: MDHCycleScrollView) -> (AnyClass)
    ///如果你自定义了cell样式，请在实现此代理方法为你的cell填充数据以及其它一系列设置
    @objc optional func setupCustomCell(cell: UICollectionViewCell, forIndex: Int, cycleScrollView: MDHCycleScrollView) -> Void
    
    ////** 点击图片回调 */
    @objc optional func cycleScrollView(cycleScrollView: MDHCycleScrollView, didSelectItemAt index: Int) -> Void
    ///图片滚动回调
    @objc optional func cycleScrollView(cycleScrollView: MDHCycleScrollView, didScrollTo index: Int) -> Void
    ///图片滚动回调 之前index和后面的index
    @objc optional func cycleScrollView(cycleScrollView: MDHCycleScrollView, scrollView: UIScrollView, formIndex: Int, toIndex: Int) -> Void
    //当偏移量改变时调用。进度范围是从0到最大索引值，这意味着一轮滚动的进度值
    @objc optional func cycleScrollView(cycleScrollView: MDHCycleScrollView, progress: CGFloat) -> Void
}


/// 轮播图 参考：SDCycleScrollView 和 ZKCycleScrollView
open class MDHCycleScrollView: UIView {
    //MARK: - === 属性
    ///图片滚动方向 滑动方向 默认是 横向滑动
    @objc open var scrollDirection = UICollectionView.ScrollDirection.horizontal {
        didSet {
            self.flowLayout.scrollDirection = self.scrollDirection
        }
    }
    /// 自动滚动间隔时间,默认3s
    @objc open var autoScrollTimeInterval: Double = 3.0 {
        didSet {
            self.addTimer()
        }
    }
    ///设置每个Cell的大小
    @objc open var itemSize = CGSize.zero {
        didSet {
            self.itemSizeFlag = true
            self.flowLayout.itemSize = itemSize
            self.flowLayout.headerReferenceSize = CGSize.init(width: (self.bounds.width-itemSize.width)/2.0, height: (self.bounds.height-itemSize.height)/2.0)
            self.flowLayout.footerReferenceSize = self.flowLayout.headerReferenceSize
        }
    }
    ///间距 Cell的间距
    @objc open var itemSpacing: CGFloat = 0 {
        didSet {
            self.flowLayout.minimumLineSpacing = itemSpacing
        }
    }
    ///cell的缩放
    @objc open var itemZoomScale: CGFloat = 1.0 {
        didSet {
            self.flowLayout.zoomScale = itemZoomScale
        }
    }
    ///是否自动滚动,默认Yes
    @objc open var autoScroll = true {
        didSet {
            self.addTimer()
        }
    }
    ///默认是。Collection是否允许拖动
    @objc open var allowsDragging = true {
        didSet {
            self.collectionView.isScrollEnabled = allowsDragging
        }
    }
    ///当前滑动到第几个视图
    @objc open var pageIndex: Int {
        get {
            return self.changeIndex(index: self.currentIndex())
        }
    }
    ///获取当前的 偏移量
    @objc open var contentOffset: CGPoint {
        get {
            if self.scrollDirection == .vertical {
                let y1 = self.collectionView.contentOffset.y-(self.flowLayout.itemSize.height+self.flowLayout.minimumLineSpacing)*2
                let maxY = max(0, y1)
                return CGPoint.init(x: 0, y: maxY)
            }else{
                let x1 = self.collectionView.contentOffset.x-(self.flowLayout.itemSize.width+self.flowLayout.minimumLineSpacing)*2
                let maxX = max(0, x1)
                return CGPoint.init(x: maxX, y: 0)
            }
        }
    }
    /** 是否无限循环,默认Yes */
    @objc open var infiniteLoop = true
    ///加载完成的回调
    @objc open var loadCompletion: VoidBlock?
    ///占位图，用于网络未加载到图片时
    @objc open var placeholderImage: UIImage? {
        didSet {
            if self.backgroundImageView == nil {
                let imv = UIImageView()
                imv.contentMode = UIView.ContentMode.scaleAspectFit
                self.insertSubview(imv, belowSubview: self.collectionView)
                self.backgroundImageView = imv
            }
            self.backgroundImageView?.image = placeholderImage
        }
    }
    ///是否只展示 文字轮播
    @objc open var onlyDisplayText = false {
        didSet {
            if onlyDisplayText && self.imageURLStringsGroup.count <= 0 {
                self.numberOfItems = titlesGroup.count
                if self.numberOfItems > 1 {
                    self.numberOfItems += 4
                }
                self.reloadData()
            }
        }
    }
    ///代理
    @objc public weak var delegate: MDHCycleScrollViewDelegate? {
        didSet {
            if delegate != nil && (delegate?.responds(to: #selector(delegate?.customCollectionViewCellClassFor(cycleScrollView:))) ?? false) {
                self.collectionView.register(delegate?.customCollectionViewCellClassFor!(cycleScrollView: self), forCellWithReuseIdentifier: cellIdentifier)
            }
        }
    }
    /** 轮播图片的ContentMode，默认为 UIViewContentModeScaleToFill */
    @objc open var bannerImageViewContentMode = UIView.ContentMode.scaleAspectFill
    /// 轮播文字label高度  高度
    @objc open var titleLabelHeight: CGFloat = 30
    ///轮播文字label字体颜色 文本的颜色
    @objc open var titleLabelTextColor = UIColor.white
    ///轮播文字label字体大小 文本的大小
    @objc open var titleLabelTextFont = UIFont.systemFont(ofSize: 13)
    ///轮播文字label背景颜色 文本的背景颜色
    @objc open var titleLabelBackgroundColor = UIColor.black.withAlphaComponent(0.5)
    /// 轮播文字label对齐方式 文本的字体的方向
    @objc public var titleLabelTextAlignment = NSTextAlignment.left
    ///设置 cell、图片的圆角
    @objc public var cellRadiusCorner: CGFloat = 0
    
    //////////////////////  数据源API //////////////////////
    ///网络图片 url string 数组 及 Image
    @objc public var imageURLStringsGroup = [Any]() {
        didSet {
            self.numberOfItems = imageURLStringsGroup.count
            if self.numberOfItems > 1 {
                self.numberOfItems += 4
            }
            self.reloadData()
        }
    }
    ////** 每张图片对应要显示的文字数组 */
    @objc public var titlesGroup = [Any]() {
        didSet {
            if onlyDisplayText && self.imageURLStringsGroup.count <= 0 {
                self.numberOfItems = titlesGroup.count
                if self.numberOfItems > 1 {
                    self.numberOfItems += 4
                }
                self.reloadData()
            }
        }
    }
    
    /// - ===== 分页 ===== -
    ///是否显示分页控件 分页控件 默认不隐藏
    @objc public var showPageControl = true
    ///是否在只有一张图时隐藏pagecontrol，默认为YES
    @objc public var hidesForSinglePage = true
    ///pagecontrol 样式，默认为动画样式
    @objc public var pageControlStyle = MDHCycleScrollViewPageControlStyle.jalapeno {
        didSet {
            self.setupPageControl()
        }
    }
    ///分页控件位置
    @objc public var pageControlAliment = MDHCycleScrollViewPageControlAliment.center
    ///分页控件距离轮播图的底部间距（在默认间距基础上）的偏移量
    @objc public var pageControlBottomOffset: CGFloat = 0
    ///分页控件距离轮播图的右边间距（在默认间距基础上）的偏移量
    @objc public var pageControlRightOffset: CGFloat = 0
    /** 当前分页控件小圆标颜色 */
    @objc public var currentPageDotColor = UIColor.white
    /** 其他分页控件小圆标颜色 */
    @objc public var pageDotColor = UIColor.lightGray
    ///两个按钮之间的间距
    @objc public var pageControlPadding: CGFloat = 8 {
        didSet {
            self.setupPageControl()
        }
    }
    /** 分页控件小圆标大小 */
    @objc public var pageControlDotSize = CGSize.init(width: 12, height: 12) {
        didSet {
            self.setupPageControl()
        }
    }
    ////分页控件 需要判断类型 及
    @objc public weak var pageControl: UIControl?
    
    ///定时器
    fileprivate var timer: Timer?
    ///是否自定义了 单元格的大小
    fileprivate var itemSizeFlag = false
    ///共有多少 数据
    fileprivate var numberOfItems = 0
    ///来自第几个图片
    fileprivate var fromIndex = 0
    ///偏移了 个数
    fileprivate var indexOffset = 0
    /// 当imageURLs为空时的背景图
    fileprivate var backgroundImageView: UIImageView?
    
    
    ///视图 滑动的视图
    @objc open lazy var collectionView: UICollectionView = {
        let cv = UICollectionView.init(frame: CGRect.zero, collectionViewLayout: self.flowLayout)
        cv.backgroundColor = UIColor.white.withAlphaComponent(0.001)
        cv.delegate = self
        cv.dataSource = self
        cv.bounces = false
        cv.scrollsToTop = false
        cv.isPagingEnabled = true
        cv.showsVerticalScrollIndicator = false
        cv.showsHorizontalScrollIndicator = false
        cv.register(MDHCycleScrollCollectionViewCell.classForCoder(), forCellWithReuseIdentifier: cellIdentifier)
        self.addSubview(cv)
        return cv
    }()
    ///layout
    @objc open lazy var flowLayout: MDHCycleScrollViewFlowLayout = {
        let ly = MDHCycleScrollViewFlowLayout()
        ly.minimumLineSpacing = 0
        ly.minimumInteritemSpacing = 0
        ly.scrollDirection = self.scrollDirection
        return ly
    }()
    
    @objc override public init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    required public init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    ///设置布局
    override open func layoutSubviews() {
        super.layoutSubviews()
        if self.itemSizeFlag {
            self.flowLayout.itemSize = self.itemSize
            self.flowLayout.headerReferenceSize = CGSize.init(width: (self.bounds.width-self.itemSize.width)/2.0, height: (self.bounds.height-self.itemSize.height)/2.0)
        }else{
            self.flowLayout.itemSize = self.bounds.size
            self.flowLayout.headerReferenceSize = CGSize.zero
        }
        self.flowLayout.footerReferenceSize = self.flowLayout.headerReferenceSize
        self.collectionView.frame = self.bounds
        
        ///分页控制器
        if self.pageControl != nil {
            let countImage = CGFloat(self.imageURLStringsGroup.count)
            var sizePage = CGSize.zero
            if self.pageControl?.isKind(of: UIPageControl.classForCoder()) ?? false {
                let pcW = self.pageControlDotSize.width*1.5*countImage
                sizePage = CGSize.init(width: pcW, height: self.pageControlDotSize.height)
            }else if self.pageControl?.isKind(of: CHIBasePageControl.classForCoder()) ?? false {
                ///感觉缺少 间距 - =
                let pcW = self.pageControlDotSize.width*countImage+(countImage-1)*self.pageControlPadding
                sizePage = CGSize.init(width: pcW, height: self.pageControlDotSize.height)
            }
            
            var pcX = (self.bounds.width-sizePage.width)/2.0
            if self.pageControlAliment == .right {
                pcX = self.bounds.width-sizePage.width-10
            }
            
            let pcY = self.bounds.height-sizePage.height-10
            
            var pageControlFrame = CGRect.init(x: pcX, y: pcY, width: sizePage.width, height: sizePage.height)
            pageControlFrame.origin.x -= self.pageControlRightOffset
            pageControlFrame.origin.y -= self.pageControlBottomOffset
            self.pageControl?.frame = pageControlFrame
            self.pageControl?.isHidden = !self.showPageControl
        }
        
        ///默认的 显示图
        if self.backgroundImageView != nil {
            self.backgroundImageView?.frame = self.bounds
        }
    }
    
    deinit {
        self.collectionView.delegate = nil
        self.collectionView.dataSource = nil
    }
    override open func willMove(toSuperview newSuperview: UIView?) {
        if newSuperview == nil {
            self.removeTimer()
        }
        super.willMove(toSuperview: newSuperview)
    }
    
    ///刷新 数据
    @objc open func reloadData() -> () {
        self.removeTimer()
        ///防止刷新时 出现界面异常
        UIView.performWithoutAnimation {
            self.collectionView.reloadData()
            self.setupPageControl()
        }
        self.collectionView.performBatchUpdates(nil) { (finished) in
            self.configuration()
            if self.loadCompletion != nil {
                self.loadCompletion!()
            }
        }
    }
    ///如果在推送或呈现新的视图控制器时，单元格卡在一半时间内，则可以在CycleScrollView所在的视图控制器的-viewWillDisplay:方法中调用此方法。
    @objc open func adjustWhenViewWillAppear() -> () {
        if self.numberOfItems < 2 {
            return
        }
        var index = self.currentIndex()
        if index == 1 {
            index = self.numberOfItems-3
        }else if index == self.numberOfItems-2 {
            index = 2
        }
        let indexPath = IndexPath.init(item: index, section: 0)
        let position = self.scrollPosition()
        self.collectionView.scrollToItem(at: indexPath, at: position, animated: false)
    }
    
    ///获取当前的 滑动到 第几个 图片
    fileprivate func currentIndex() -> Int {
        var index = 0
        
        if self.numberOfItems < 2 || self.bounds.width <= 0 || self.bounds.height <= 0 {
            return index
        }
        
        ///偏移量
        let contentOffset = self.collectionView.contentOffset
        ///
        let layout = self.flowLayout
        ///
        let minimumLineSpacing = layout.minimumLineSpacing
        ///
        let itemSize = layout.itemSize
        
        switch self.scrollDirection {
        case .horizontal:///水平
            let heightSpace = (itemSize.width+minimumLineSpacing)
            index = Int((contentOffset.x+heightSpace/2.0)/heightSpace)
            break
        default:///垂直
            let heightSpace = (itemSize.height+minimumLineSpacing)
            index = Int((contentOffset.y+heightSpace/2.0)/heightSpace)
            break
        }
        if !self.infiniteLoop && index == self.numberOfItems - 3 {
            return self.numberOfItems-4
        }
        return min(self.numberOfItems-2, max(1, index))
    }
    ///获取到下一个
    fileprivate func changeIndex(index: Int) -> Int {
        var nextIndex = index
        if self.numberOfItems > 1 {
            if index == 0 {
                nextIndex = self.numberOfItems-6
            }else if index == 1 {
                nextIndex = self.numberOfItems-5
            } else if index == self.numberOfItems - 2 {
                //nextIndex = self.infiniteLoop ? 0:index-3
                nextIndex = 0
                if !self.infiniteLoop {
                    nextIndex = self.numberOfItems-5
                }
            } else if index == self.numberOfItems - 1 {
                nextIndex = 1
            } else {
                nextIndex -= 2
            }
        }
        return nextIndex
    }
    
    ///Cell 的滑动 方向 获取
    fileprivate func scrollPosition() -> UICollectionView.ScrollPosition {
        return self.flowLayout.scrollDirection == .vertical ? .centeredVertically:.centeredHorizontally
    }
    
    ///重新加载
    fileprivate func configuration() -> () {
        self.fromIndex = 0
        self.indexOffset = 0
        if self.numberOfItems >= 2 {
            let position = self.scrollPosition()
            let indexPath = IndexPath.init(item: 2, section: 0)
            self.collectionView.scrollToItem(at: indexPath, at: position, animated: false)
            
            self.addTimer()
            self.updatePageControl()
        }
    }
}

///分页相关 PageControl
extension MDHCycleScrollView {
    ///更新分页
    fileprivate func updatePageControl() -> () {
        if self.pageControl != nil {
            let pc = self.pageControl as? UIPageControl
            pc?.currentPage = 0
            pc?.numberOfPages = max(0, self.numberOfItems-4)
            if self.hidesForSinglePage && !self.showPageControl {///单个的时候 是否需要隐藏分页
                pc?.isHidden = (pc?.numberOfPages ?? 0) < 2
            }else{
                pc?.isHidden = !self.showPageControl
            }
        }
    }
    ///设置分页控制器
    fileprivate func setupPageControl() -> () {
        //// 重新加载数据时调整
        if self.pageControl != nil {
            self.pageControl?.removeFromSuperview()
            self.pageControl = nil
        }
        ///没有图片数据 并且只显示 文字
        if self.imageURLStringsGroup.count <= 0 || self.onlyDisplayText {
            return
        }
        ///只有一张图片时 并且允许隐藏
        if self.imageURLStringsGroup.count <= 1 && self.hidesForSinglePage {
            return
        }
        ///当前是第几个
        let indexOnPageControl = self.changeIndex(index: self.currentIndex())
        switch self.pageControlStyle {
        case .classic:///系统的
            let pc = UIPageControl()
            pc.numberOfPages = self.imageURLStringsGroup.count
            pc.currentPageIndicatorTintColor = self.currentPageDotColor
            pc.pageIndicatorTintColor = self.pageDotColor
            pc.isUserInteractionEnabled = false
            pc.currentPage = indexOnPageControl
            self.addSubview(pc)
            self.pageControl = pc
            break
        default:
            var bpc = CHIBasePageControl()
            switch self.pageControlStyle {
            case .jalapeno:///默认情况
                let bpc1 = CHIPageControlJalapeno()
                bpc1.radius = self.pageControlDotSize.width
                bpc = bpc1
                break
            case .aleppo:
                bpc = CHIPageControlAleppo()
                break
            case .jaloro:
                let bpc1 = CHIPageControlJaloro()
                bpc1.elementWidth = self.pageControlDotSize.width
                bpc1.elementHeight = self.pageControlDotSize.height
                bpc = bpc1
                bpc.radius = 3
                break
            case .chimayo:
                bpc = CHIPageControlChimayo()
                break
            case .puya:
                bpc = CHIPageControlPuya()
                break
            case .paprika:
                bpc = CHIPageControlPaprika()
                break
            case .fresno:
                bpc = CHIPageControlFresno()
                break
            case .aji:
                bpc = CHIPageControlAji()
                break
            default:
                break
            }
            bpc.numberOfPages = self.imageURLStringsGroup.count
            bpc.currentPageTintColor = self.currentPageDotColor
            bpc.tintColor = self.pageDotColor
            bpc.padding = self.pageControlPadding
            bpc.transform = CGAffineTransform.init(scaleX: 0.5, y: 0.5)

            self.addSubview(bpc)
            self.pageControl = bpc
            break
        }
    }
}

///定时器相关 -
extension MDHCycleScrollView {
    ///添加定时器
    fileprivate func addTimer() -> () {
        ///销毁定时器
        self.removeTimer()
        ///判断条件 是否需要添加 定时器
        if numberOfItems < 2 || !self.autoScroll || self.autoScrollTimeInterval <= 0.0 {
            return
        }
        let tim = Timer.init(timeInterval: self.autoScrollTimeInterval, target: self, selector: #selector(timerMethod), userInfo: nil, repeats: true)
        self.timer = tim
        ///添加到runloop上 使其开始运作
        RunLoop.main.add(tim, forMode: RunLoop.Mode.common)
    }
    
    ////定时器
    @objc fileprivate func timerMethod() -> () {
        let index = self.currentIndex()+1
        let position = self.scrollPosition()
        let indexPath = IndexPath.init(item: index, section: 0)
        self.collectionView.scrollToItem(at: indexPath, at: position, animated: true)
    }
    
    ///销毁定时器
    fileprivate func removeTimer() -> () {
        if self.timer != nil {
            self.timer?.invalidate()
            self.timer = nil
        }
    }
}



///UICollectionView -
extension MDHCycleScrollView: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
    open func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return self.numberOfItems
    }
    
    open func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath)
        
        ///当前的单元格
        let itemIndex = self.changeIndex(index: indexPath.item)
        if self.delegate != nil && (self.delegate?.responds(to: #selector(self.delegate?.setupCustomCell(cell:forIndex:cycleScrollView:))) ?? false) && (self.delegate?.responds(to: #selector(self.delegate?.customCollectionViewCellClassFor(cycleScrollView:))) ?? false) {
            self.delegate?.setupCustomCell!(cell: cell, forIndex: itemIndex, cycleScrollView: self)
            return cell
        }
        
        let cell1 = cell as? MDHCycleScrollCollectionViewCell
        if !self.onlyDisplayText {
            ///进行复制
            let imagePath = self.imageURLStringsGroup[itemIndex]
            if imagePath is String {
                let imageName = imagePath as? String ?? ""
                if imageName.hasPrefix("http") {
                    cell1?.imageView?.sd_setImage(with: URL.init(string: imageName), placeholderImage: self.placeholderImage)
                }else{
                    var image = UIImage.init(named: imageName)
                    if image == nil {//&& (image?.size.width != 0 || image?.size.height != 0)
                        image = UIImage.init(contentsOfFile: imageName)
                    }
                    if image == nil {//&& (image?.size.width != 0 || image?.size.height != 0)
                        image = self.placeholderImage
                    }
                    cell1?.imageView?.image = image
                }
            }else if imagePath is UIImage {
                cell1?.imageView?.image = imagePath as? UIImage// ?? UIImage()
            }
        }
        
        self.backgroundImageView?.isHidden = true
        
        let titleCount = self.titlesGroup.count
        if titleCount > 0 && itemIndex < titleCount {
            let title = self.titlesGroup[itemIndex]
            if title is String {
                cell1?.titleLabel?.text = title as? String
            }else if title is NSAttributedString {
                cell1?.titleLabel?.attributedText = title as? NSAttributedString
            }else if title is NSMutableAttributedString {
                cell1?.titleLabel?.attributedText = title as? NSMutableAttributedString
            }
            cell1?.titleLabel?.isHidden = false
        }else{
            cell1?.titleLabel?.isHidden = true
        }
        
        if !(cell1?.hasConfigured ?? false) {
            cell1?.titleLabelBackgroundColor = self.titleLabelBackgroundColor
            cell1?.titleLabelHeight = self.titleLabelHeight
            cell1?.titleLabelTextAlignment = self.titleLabelTextAlignment
            cell1?.titleLabelTextColor = self.titleLabelTextColor
            cell1?.titleLabelTextFont = self.titleLabelTextFont
            cell1?.hasConfigured = true
            cell1?.imageView?.contentMode = self.bannerImageViewContentMode
            cell1?.clipsToBounds = true
            cell1?.onlyDisplayText = self.onlyDisplayText
        }
        if self.cellRadiusCorner > 0 {
            cell.dh_cornerRadius = self.cellRadiusCorner
            cell1?.imageView?.dh_cornerRadius = self.cellRadiusCorner
        }
        return cell
    }
    
    ///点击事件
    open func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        if self.delegate != nil && (self.delegate?.responds(to: #selector(self.delegate?.cycleScrollView(cycleScrollView:didSelectItemAt:))) ?? false) {
            ///当前的单元格
            let itemIndex = self.changeIndex(index: indexPath.item)
            self.delegate?.cycleScrollView!(cycleScrollView: self, didSelectItemAt: itemIndex)
        }
    }
    
    ///
    open func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool {
        return true
    }
    ///
    open func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath) {
        self.removeTimer()
    }
    ///
    open func collectionView(_ collectionView: UICollectionView, didUnhighlightItemAt indexPath: IndexPath) {
        self.addTimer()
    }
    /// - ==== scrollViewDidScroll
    ///
    open func scrollViewDidScroll(_ scrollView: UIScrollView) {
        var total: CGFloat = 0.0
        var offset: CGFloat = 0.0
        let itemSize = self.flowLayout.itemSize
        let minimumLineSpacing = self.flowLayout.minimumLineSpacing
        if self.scrollDirection == .vertical {
            total = CGFloat((self.numberOfItems - 5)) * (itemSize.height + minimumLineSpacing)
            offset = fmod(self.contentOffset.y, (itemSize.height + minimumLineSpacing) * CGFloat((self.numberOfItems - 4)))
        }else{
            total = CGFloat((self.numberOfItems - 5)) * (itemSize.width + minimumLineSpacing)
            offset = fmod(self.contentOffset.x, (itemSize.width + minimumLineSpacing) * CGFloat((self.numberOfItems - 4)))
        }
        let percent = offset/total
        let progress = percent*CGFloat(self.numberOfItems - 5)
        
        if self.delegate != nil && self.delegate?.responds(to: #selector(self.delegate?.cycleScrollView(cycleScrollView:progress:))) ?? false {
            self.delegate?.cycleScrollView!(cycleScrollView: self, progress: progress)
        }
        
        if self.pageControl != nil {
            let currentPage = self.pageIndex
            (self.pageControl as? UIPageControl)?.currentPage = currentPage
            (self.pageControl as? CHIBasePageControl)?.progress = Double(progress)
        }
    }
    ///scrollViewWillBeginDragging
    open func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
        self.removeTimer()
    }
    ///scrollViewDidEndDragging
    open func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        self.addTimer()
    }
    ///scrollViewDidEndScrollingAnimation
    open func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
        let index = self.currentIndex()
        let position = self.scrollPosition()
        if index == 1 {
            let indexPath = IndexPath.init(item: self.numberOfItems-3, section: 0)
            self.collectionView.scrollToItem(at: indexPath, at: position, animated: false)
        }else if index == self.numberOfItems - 2 {
            let indexPath = IndexPath.init(item: 2, section: 0)
            self.collectionView.scrollToItem(at: indexPath, at: position, animated: false)
        }
        let toIndex = self.changeIndex(index: index)
        if self.delegate != nil && self.delegate?.responds(to: #selector(self.delegate?.cycleScrollView(cycleScrollView:scrollView:formIndex:toIndex:))) ?? false {
            self.delegate?.cycleScrollView!(cycleScrollView: self, scrollView: scrollView, formIndex: index, toIndex: toIndex)
        }
        if self.delegate != nil && self.delegate?.responds(to: #selector(self.delegate?.cycleScrollView(cycleScrollView:didScrollTo:))) ?? false {
            self.delegate?.cycleScrollView!(cycleScrollView: self, didScrollTo: toIndex)
        }
        self.fromIndex = toIndex
    }
    //scrollViewWillEndDragging
    open func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
        let index = self.pageIndex
        if index != self.fromIndex {
            return
        }
        let sum = velocity.x+velocity.y
        if sum > 0 {
            self.indexOffset = 1
        }else if sum < 0 {
            self.indexOffset = -1
        }else{
            self.indexOffset = 0
        }
    }
    ///scrollViewWillBeginDecelerating
    open func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView) {
        let index = self.currentIndex()+self.indexOffset
        let position = self.scrollPosition()
        let indexPath = IndexPath.init(item: index, section: 0)
        self.collectionView.scrollToItem(at: indexPath, at: position, animated: true)
        self.indexOffset = 0
    }
}



///Layout
open class MDHCycleScrollViewFlowLayout: UICollectionViewFlowLayout {
    ///default 1.f, it ranges from 0.f to 1.f
    @objc public var zoomScale: CGFloat = 1.0
    
    ///返回给定rect中所有视图的数组布局属性实例 重新设置布局
    override open func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        let attributes = super.layoutAttributesForElements(in: rect) ?? [UICollectionViewLayoutAttributes]()
        ///是否是 垂直滑动
        let isVer = self.scrollDirection == .vertical
        
        var offset = self.collectionView?.bounds.midX ?? 0
        var distanceForScale = self.itemSize.width + self.minimumLineSpacing
        if isVer {
            offset = self.collectionView?.bounds.midY ?? 0
            distanceForScale = self.itemSize.height + self.minimumLineSpacing
        }
        for attr in attributes {
            var scale: CGFloat = 0.0
            var distance = abs(offset-attr.center.x)
            if isVer {
                distance = abs(offset-attr.center.y)
            }
            
            if distance >= distanceForScale {
                scale = self.zoomScale
            }else if distance == 0 {
                scale = 1.0
                attr.zIndex = 1
            }else {
                scale = self.zoomScale+(distanceForScale-distance)*(1-self.zoomScale)/distanceForScale
            }
            attr.transform = CGAffineTransform.init(scaleX: scale, y: scale)
        }
        return attributes
    }
    
    ///返回“是”以使集合视图重新查询几何图形信息的布局
    override open func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
        return true
    }
}


///CollectionCell
open class MDHCycleScrollCollectionViewCell: UICollectionViewCell {
    ///imageView
    @objc weak var imageView: UIImageView?
    ///只展示文字轮播
    @objc public var onlyDisplayText = false
    /*///文字
    @objc public var title = "" {
        didSet {
            self.titleLabel?.text = title
            if self.titleLabel?.isHidden ?? true {
                self.titleLabel?.isHidden = false
            }
            self.titleLabel?.isHidden = title.count <= 0
        }
    }
    */
    ///高度
    @objc public var titleLabelHeight: CGFloat = 0
    ///文本的颜色
    @objc public var titleLabelTextColor = UIColor.black {
        didSet {
            self.titleLabel?.textColor = titleLabelTextColor
        }
    }
    ///文本的大小
    @objc public var titleLabelTextFont = UIFont.systemFont(ofSize: 13) {
        didSet {
            self.titleLabel?.font = titleLabelTextFont
        }
    }
    ///文本的背景颜色
    @objc public var titleLabelBackgroundColor = UIColor.white {
        didSet {
            self.titleLabel?.backgroundColor = titleLabelBackgroundColor
        }
    }
    ///文本的字体的方向
    @objc public var titleLabelTextAlignment = NSTextAlignment.center {
        didSet {
            self.titleLabel?.textAlignment = titleLabelTextAlignment
        }
    }
    ///是否已经设置完成了属性
    @objc public var hasConfigured = false
    
    ///文本
    fileprivate var titleLabel: UILabel?

    
    ///初始化
    override public init(frame: CGRect) {
        super.init(frame: frame)
        ///图片
        let imv = UIImageView()
        self.contentView.addSubview(imv)
        self.imageView = imv
        
        ///文本
        let label = UILabel()
        label.isHidden = true
        self.contentView.addSubview(label)
        self.titleLabel = label
    }
    required public init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override open func layoutSubviews() {
        super.layoutSubviews()
        if self.onlyDisplayText {
            self.titleLabel?.frame = self.bounds
        }else{
            self.imageView?.frame = self.bounds
            let titFWidth = self.bounds.width
            let titFHeight = self.titleLabelHeight
            let titFX = (self.bounds.width-titFWidth)/2.0
            let titFY = self.bounds.height-titFHeight
            self.titleLabel?.frame = CGRect.init(x: titFX, y: titFY, width: titFWidth, height: titFHeight)
        }
    }
    
}
